library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;


entity graphicsHandler is
  port(clk50_in 		: in std_logic;
		 data_in 		: in std_logic_vector(11 downto 0);
		 user_coords	: in std_logic_vector(19 downto 0);
		 coords_in		: in std_logic_vector(19 downto 0);
		 rgb_out			: out std_logic_vector(11 downto 0);
		 left_in			: in std_logic;
		 right_in		: in std_logic;
		 mode				: in std_logic
		 );
end graphicsHandler;

architecture Behavioral of graphicsHandler is

signal clk : std_logic :='0';
signal clk25 : std_logic :='0';
signal locomotion : std_logic_vector (9 downto 0) := "0000000000";
signal motionloco : std_logic_vector (19 downto 10) :="0000000000";

signal tmpCol : std_logic_vector (11 downto 0) := X"000";

signal white : std_logic_vector (11 downto 0) := X"FFF";
signal black : std_logic_vector (11 downto 0) := X"000";
signal red : std_logic_vector (11 downto 0) := X"F00";
signal green : std_logic_vector (11 downto 0) := X"0F0";
signal blue : std_logic_vector (11 downto 0) := X"00F";
signal orange : std_logic_vector (11 downto 0) := X"FB0";
signal brown : std_logic_vector (11 downto 0) :=X"852";

begin
	process(clk25)
	
	variable prg : integer:=0;
	variable inter : integer:=50;
		
	variable deltaX : integer:=0;
	variable deltaY : integer:=0;
	
	variable tmpR : std_logic_vector (3 downto 0) := X"F";
	variable tmpG : std_logic_vector (3 downto 0) := X"0";
	variable tmpB : std_logic_vector (3 downto 0) := X"0";
	variable toneBlock : integer := 0;
	
	variable hat : std_logic :='0';
	variable arm : integer :=0;
	variable hold : integer :=0;
	
	begin
	
	if (falling_edge(clk25))
	then
	
		rgb_out <= data_in; --Basic color from data_in
			
		if(mode = '0' and hold = 0)
		then
			prg := prg+1;
			hold := 1;
		elsif(mode = '1' and hold = 1)
		then
			hold := 0;
		end if;
		
		if(prg >= 5)
		then
			prg := 0;
		end if;
			
			
		if(prg = 0) -- Color test
		then
		
			if(coords_in(19 downto 10) <= conv_std_logic_vector(inter,10))
			then
				rgb_out <= red;
			end if;
			
			if(coords_in(19 downto 10) >= conv_std_logic_vector(inter*1,10) and coords_in(19 downto 10) <= conv_std_logic_vector(inter*2,10))
			then
				rgb_out <= green;	
			end if;
			
			if(coords_in(19 downto 10) >= conv_std_logic_vector(inter*2,10) and coords_in(19 downto 10) <= conv_std_logic_vector((inter*3),10))
			then
				rgb_out <= blue;
			end if;
					
			if(coords_in(19 downto 10) >= conv_std_logic_vector(inter*3,10) and coords_in(19 downto 10) <= conv_std_logic_vector(inter*4,10))
			then
				rgb_out <= orange;	
			end if;
			
			if(coords_in(19 downto 10) >= conv_std_logic_vector(inter*4,10) and coords_in(19 downto 10) <= conv_std_logic_vector((inter*5),10))
			then
				rgb_out <= blue;
			end if;
					
			if(coords_in(19 downto 10) >= conv_std_logic_vector(inter*5,10) and coords_in(19 downto 10) <= conv_std_logic_vector((inter*6),10))
			then
				rgb_out <= green;
			end if;
			
			if(coords_in(19 downto 10) >= conv_std_logic_vector(inter*6,10) and coords_in(19 downto 10) <= conv_std_logic_vector((inter*7),10))
			then
				rgb_out <= red;
			end if;
		
		end if;
				
		if(prg = 1) --TWO MOVING BLOCKS
		then
			if(coords_in(9 downto 0) >= locomotion and coords_in(9 downto 0) <= locomotion+conv_std_logic_vector(10,10))
			then
				rgb_out <= orange;
			end if;
			
			if(coords_in(19 downto 10) >= motionloco and coords_in(19 downto 10) <= motionloco+conv_std_logic_vector(80,10))
			then
				rgb_out <= "000111110001";
			end if;
		end if;		
		
		if(prg = 3) --TONE
		then
			
			CASE toneBlock IS
				WHEN 0 =>
					tmpR := X"F";
					
					if ((conv_integer(coords_in(19 downto 10)) mod 7) = 0)
					then
						tmpG := tmpG + X"1";
					end if;
					
					tmpB := X"0";
				WHEN 1 =>
					if ((conv_integer(coords_in(19 downto 10)) mod 7) = 0)
					then
						tmpR := tmpR - X"1";
					end if;
					
					tmpG := X"F";
					tmpB := X"0";
				WHEN 2 =>
					tmpR := X"0";
					tmpG := X"F";
					
					if ((conv_integer(coords_in(19 downto 10)) mod 7) = 0)
					then
						tmpB := tmpB + X"1";
					end if;
				WHEN 3 =>
					tmpR := X"0";
					
					if ((conv_integer(coords_in(19 downto 10)) mod 7) = 0)
					then
						tmpG := tmpG - X"1";
					end if;
					
					tmpB := X"F";
				WHEN 4 =>
					if ((conv_integer(coords_in(19 downto 10)) mod 7) = 0)
					then
						tmpR := tmpR + X"1";
					end if;
					
					tmpG := X"0";
					tmpB := X"F";
				WHEN 5 =>
					tmpR := X"F";
					tmpG := X"0";
					
					if ((conv_integer(coords_in(19 downto 10)) mod 7) = 0)
					then
						tmpB := tmpB - X"1";
					end if;
					
				WHEN OTHERS => null;
			END CASE;
			
			--Next toneBlock?
			if ((conv_integer(coords_in(19 downto 10)) mod 106) = 0)
			then
				toneBlock := toneBlock + 1;
			end if;
			
			--Reset after each row
			if ((conv_integer(coords_in(19 downto 10)) mod 640) = 0)
			then
				tmpR := X"F";
				tmpG := X"0";
				tmpB := X"0";
				toneBlock :=0;
			end if;
			
			rgb_out <= tmpR & tmpG & tmpB;
		end if;
		
		if(prg = 4) --SNOW MAN
		then
		
			if (user_coords(9 downto 0) < conv_std_logic_vector(250,10))
				then
				hat :='1';		
			else
				hat :='0';
			end if;
			
			if (left_in = '1')
			then
				arm := 1;
			elsif (right_in = '1')
			then
				arm := 2;
			else
				arm := 0;
			end if;
			
			-- ARMAR
			if(coords_in(9 downto 0) >= conv_std_logic_vector(320, 10) and
			coords_in(9 downto 0) <= conv_std_logic_vector(325, 10))
			then
				if(coords_in(19 downto 10) >= user_coords(19 downto 10) + conv_std_logic_vector(30,10) and
				coords_in(19 downto 10) <= user_coords(19 downto 10) + conv_std_logic_vector(70,10))
				then
					rgb_out <= brown;
				end if;
			
				if(coords_in(19 downto 10) >= user_coords(19 downto 10) - conv_std_logic_vector(70,10) and
				coords_in(19 downto 10) <= user_coords(19 downto 10) - conv_std_logic_vector(30,10))
				then
					rgb_out <= brown;
				end if;
			end if;
			
			if(arm = 0 and
			coords_in(9 downto 0) >= conv_std_logic_vector(320, 10) and
			coords_in(9 downto 0) <= conv_std_logic_vector(325, 10))
			then
				if(coords_in(19 downto 10) >= user_coords(19 downto 10) + conv_std_logic_vector(70,10) and
				coords_in(19 downto 10) <= user_coords(19 downto 10) + conv_std_logic_vector(110,10))
				then
					rgb_out <= brown;
				end if;
			
				if(coords_in(19 downto 10) >= user_coords(19 downto 10) - conv_std_logic_vector(110,10) and
				coords_in(19 downto 10) <= user_coords(19 downto 10) - conv_std_logic_vector(70,10))
				then
					rgb_out <= brown;
				end if;
			
			elsif(arm = 2)
			then
				if(coords_in(9 downto 0) >= conv_std_logic_vector(280,10) and
				coords_in(9 downto 0) <= conv_std_logic_vector(320,10) and
				coords_in(19 downto 10) >= user_coords(19 downto 10) + conv_std_logic_vector(65,10) and
				coords_in(19 downto 10) <= user_coords(19 downto 10) + conv_std_logic_vector(70,10))
				then
					rgb_out <= brown;
				end if;
				
				if(coords_in(9 downto 0) >= conv_std_logic_vector(325,10) and
				coords_in(9 downto 0) <= conv_std_logic_vector(365,10) and
				coords_in(19 downto 10) >= user_coords(19 downto 10) - conv_std_logic_vector(70,10) and
				coords_in(19 downto 10) <= user_coords(19 downto 10) - conv_std_logic_vector(65,10))
				then
					rgb_out <= brown;
				end if;
				
			elsif(arm = 1)	
			then
				if(coords_in(9 downto 0) >= conv_std_logic_vector(325,10) and
				coords_in(9 downto 0) <= conv_std_logic_vector(365,10) and
				coords_in(19 downto 10) >= user_coords(19 downto 10) + conv_std_logic_vector(65,10) and
				coords_in(19 downto 10) <= user_coords(19 downto 10) + conv_std_logic_vector(70,10))
				then
					rgb_out <= brown;
				end if;
				
				if(coords_in(9 downto 0) >= conv_std_logic_vector(280,10) and
				coords_in(9 downto 0) <= conv_std_logic_vector(320,10) and
				coords_in(19 downto 10) >= user_coords(19 downto 10) - conv_std_logic_vector(70,10) and
				coords_in(19 downto 10) <= user_coords(19 downto 10) - conv_std_logic_vector(65,10))
				then
					rgb_out <= brown;
				end if;
			end if;
		
			--TJCOKBOLLEN
			deltaY := abs(conv_integer(coords_in(9 downto 0)) - 390);
			deltaX := abs(conv_integer(coords_in(19 downto 10)) - conv_integer(user_coords(19 downto 10)));
			
			if ((deltaY*deltaY) + (deltaX*deltaX) <= (40*40))
			then
				rgb_out <= white;
			end if;
			
			--ÖVRE BOLLEN
			deltaY := abs(conv_integer(coords_in(9 downto 0)) - 325);
			deltaX := abs(conv_integer(coords_in(19 downto 10)) - conv_integer(user_coords(19 downto 10)));
			
			if ((deltaY*deltaY) + (deltaX*deltaX) <= (30*30))
			then
				rgb_out <= white;
			end if;
			
			--MELLAN BOLLEN
			deltaY := abs(conv_integer(coords_in(9 downto 0)) - 275);
			deltaX := abs(conv_integer(coords_in(19 downto 10)) - conv_integer(user_coords(19 downto 10)));
			
			if ((deltaY*deltaY) + (deltaX*deltaX) <= (25*25))
			then
				rgb_out <= white;
			end if;
			
			-- ÖGON
			deltaY := abs(conv_integer(coords_in(9 downto 0)) - 270);
			deltaX := abs(conv_integer(coords_in(19 downto 10)) - conv_integer(user_coords(19 downto 10))-10);
			if ((deltaY*deltaY) + (deltaX*deltaX) <= (25))
			then
				rgb_out <= black;
			end if;
			
			deltaY := abs(conv_integer(coords_in(9 downto 0)) - 270);
			deltaX := abs(conv_integer(coords_in(19 downto 10)) - conv_integer(user_coords(19 downto 10))+10);
			if ((deltaY*deltaY) + (deltaX*deltaX) <= (25))
			then
				rgb_out <= black;
			end if;
			-- END ÖGON
			
			-- MUNBOLLEN
			deltaY := abs(conv_integer(coords_in(9 downto 0)) - 280);
			deltaX := abs(conv_integer(coords_in(19 downto 10)) - conv_integer(user_coords(19 downto 10)));
			
			if ((deltaY*deltaY) + (deltaX*deltaX) <= (100)		
			and conv_integer(coords_in(9 downto 0)) >= (280)
			and hat = '0')
			then
				rgb_out <= black;
			end if;
			
			deltaY := abs(conv_integer(coords_in(9 downto 0)) - 290);
			deltaX := abs(conv_integer(coords_in(19 downto 10)) - conv_integer(user_coords(19 downto 10)));
			
			if ((deltaY*deltaY) + (deltaX*deltaX) <= (100)		
			and conv_integer(coords_in(9 downto 0)) <= (290)
			and hat = '1')
			then
				rgb_out <= black;
			end if;
			
			--HATTEN
			if(coords_in(9 downto 0) >= user_coords(9 downto 0) - conv_std_logic_vector(10,10) and
			coords_in(9 downto 0) <= user_coords(9 downto 0) and
			coords_in(19 downto 10) >= user_coords(19 downto 10) - conv_std_logic_vector(25,10) and
			coords_in(19 downto 10) <= user_coords(19 downto 10) + conv_std_logic_vector(25,10))
			then
				rgb_out <= black;
			end if;
			
			if(coords_in(9 downto 0) >= user_coords(9 downto 0) - conv_std_logic_vector(35,10) and
			coords_in(9 downto 0) <= user_coords(9 downto 0) and
			coords_in(19 downto 10) >= user_coords(19 downto 10) - conv_std_logic_vector(15,10) and
			coords_in(19 downto 10) <= user_coords(19 downto 10) + conv_std_logic_vector(15,10))
			then
				rgb_out <= black;
			end if;
			
			-- SNÖ
				if(coords_in(9 downto 0) >= conv_std_logic_vector(420,10))
			then
				rgb_out <= white;
			end if;
		
		end if; --END CLOCK FALLING EDGE
		
	end if; --END CLOCK SENSITIVITY
			
	end process;
	
	--GENERATES THE 25Mhz pixel clock
	process (clk50_in)
	begin
	  if rising_edge(clk50_in) then
		 clk25 <= NOT(clk25);
	  end if;
	end process;

	--GENERATES THE 50Hz pixel clock (for locomotion)
	process (clk50_in)
		
		variable cycles : integer := 1;
		begin
		
		if rising_edge(clk50_in) then
			
			if (cycles=50000000/50) then
				cycles := 1;
				clk <= NOT(clk);
			end if;
			
			cycles := cycles+1;
			
		end if;
	end process;
	
	--Makes locomotion move
	process(clk)
		variable du : integer :=0;
		begin
	
		if (rising_edge(clk))
			then
				
			if(locomotion="0110010000" and du=0)
				then
				du:=1;
			elsif(locomotion="0000000000" and du=1)
			then
				du:=0;
			end if;
				
			if(du=1)
				then
				locomotion <= locomotion-"0000000001";
			elsif(du=0)
			then
				locomotion <= locomotion+"0000000001";
			end if;
			
		end if;
		
	end process;
	
	--Makes locomotion turn up/down
	process(clk)
		variable du2 : integer :=0;
		begin
	
		if (rising_edge(clk))
			then
				
			if(motionloco>="1000110000" and du2=0)
				then
				du2:=1;
			elsif(motionloco<="0000000000" and du2=1)
			then
				du2:=0;
			end if;
				
			if(du2=1)
				then
				motionloco <= motionloco-"0000000011";
			elsif(du2=0)
			then
				motionloco <= motionloco+"0000000011";
			end if;
			
		end if;
		
	end process;

end Behavioral;